import asyncio
import json
import os.path
import random
import time

from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import action
from . import gitlabApi
from utils.views import ElMessage
import difflib
from django.http import JsonResponse
import gitlab
from utils.views import ddSend, FsLog

from celery import shared_task
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from myproject.celery import app


"""
    获取项目列表
"""


class gitlabProjects(viewsets.ViewSet,
                     viewsets.mixins.ListModelMixin,
                     viewsets.mixins.RetrieveModelMixin,
                     viewsets.mixins.CreateModelMixin,
                     viewsets.mixins.UpdateModelMixin, ):

    ## 获取所有项目组，返回给穿梭框
    def list(self, request, *args, **kwargs):
        gitlabClient = gitlabApi.gitlabClient()
        projects = self.projectsFromToken(gitlabClient)
        projects_list = []
        for project in projects:
            projects_list.append({"key": project.id, "label": project.name})
        return Response(ElMessage(data=projects_list, type="success"), status=status.HTTP_200_OK)

    def create(self, request, *args, **kwargs):
        print("create")
        return Response({"msg": 666})

    ## 通过 token 获取 Project
    def projectsFromToken(self, gitlabClient):
        projects = gitlabClient.projects.list()
        return projects

    ## 通过 ProjectID 获取 Project
    def projectsFromId(self, gitlabClient, ProjectID_list):
        projects = gitlabClient.projects.list(all=True)
        ProjectList = []
        for project in projects:
            if project.id in ProjectID_list:
                ProjectList.append(project)
        return ProjectList


"""
    文件比对接口
"""
class fileDiff(viewsets.ViewSet,
               viewsets.mixins.ListModelMixin,
               viewsets.mixins.RetrieveModelMixin,
               viewsets.mixins.CreateModelMixin,
               viewsets.mixins.UpdateModelMixin, ):

    def create(self, request, *args, **kwargs):

        gitlabClient = gitlabApi.gitlabClient()
        res = []

        data = request.data
        # print("data:", data)
        # print("data_list", list(data))
        for item in data:
            try:
                instance = dict(item)
                srcProjectID = instance["src"][0]
                srcRef = instance["src"][2]
                srcFilePath = instance["srcPath"][0]
                destProjectID = instance["dest"][0]
                destRef = instance["dest"][2]
                destFilePath = instance["destPath"][0]

                srcProject = gitlabClient.projects.get(srcProjectID)
                destProject = gitlabClient.projects.get(destProjectID)
                srcFile = srcProject.files.raw(file_path=srcFilePath, ref=srcRef)
                destFile = destProject.files.raw(file_path=destFilePath, ref=destRef)
                # print("srcContent:", srcFile.decode(), "destContent:", destFile.decode())

                diff = difflib.unified_diff(srcFile.decode().splitlines(keepends=True),
                                            destFile.decode().splitlines(keepends=True),
                                            fromfile=f'{srcProject.name}/{srcRef}/{srcFilePath}',
                                            tofile=f'{destProject.name}/{destRef}/{destFilePath}', lineterm='')
                string = '\n'.join(list(diff))
                # print("diff_list:-----", string)
                res.append(string)
                # return JsonResponse({"diff": '\n'.join(diff)})
            except Exception as e:
                # return JsonResponse({"error": str(e)}, status=500)
                return JsonResponse(ElMessage(msg=str(e)), status=500)
        return Response(ElMessage(data='\n'.join(res), type="success"), status=status.HTTP_200_OK)
        # path = os.path.dirname(os.path.abspath(__file__))
        #
        # com1,com2 = self.compare_files(os.path.join(path, 'file1.txt'), os.path.join(path, 'file2.txt'))
        #
        # try:
        #     diff = difflib.unified_diff(com1,com2, fromfile='file1.txt', tofile='file2.txt', lineterm='')
        #     return JsonResponse({"diff": '\n'.join(diff)})
        # except Exception as e:
        #     return JsonResponse({"error": str(e)}, status=500)

        # try:
        #     diff = list(unified_diff("abc\naaa", "abc\naab"))
        #     return JsonResponse({"diff": "".join(diff)})
        # except Exception as e:
        #     return JsonResponse({"error": str(e)}, status=500)
        # finally:
        #     # 清理临时目录（在生产环境中需谨慎处理）
        #     # shutil.rmtree('/tmp/temp_repo')
        #     print("清理目录")

    def compare_files(self, file1, file2):
        with open(file1, 'r') as f1, open(file2, 'r') as f2:
            lines1 = f1.readlines()
            lines2 = f2.readlines()

        return lines1, lines2



"""
    本地上传文件比对接口
"""
import shutil
class LocalFileDiff(viewsets.ViewSet,
               viewsets.mixins.ListModelMixin,
               viewsets.mixins.RetrieveModelMixin,
               viewsets.mixins.CreateModelMixin,
               viewsets.mixins.UpdateModelMixin, ):

    authentication_classes = []
    def create(self, request, *args, **kwargs):
        # 确保收到两个文件
        if len(request.FILES) != 2:
            return JsonResponse({"success": False, "message": "Please upload exactly two files."}, status=400)

        # 获取上传的文件
        file1 = request.FILES['file0']
        file2 = request.FILES['file1']

        # BASE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)),"upload")
        # if not os.path.exists(BASE_DIR):
        #     os.makedirs(BASE_DIR)

        res = []

        # 读取文件内容
        with file1.open(mode='rt') as f1, file2.open(mode='rt') as f2:
            content1 = f1.read().decode('utf-8')
            content2 = f2.read().decode('utf-8')

        # 使用difflib进行比较
        diff = difflib.unified_diff(content1.splitlines(), content2.splitlines(), fromfile=file1.name,
                                    tofile=file2.name, lineterm='')
        try:
            diff_result = '\n'.join(list(diff))  # 将结果转换为字符串
        except Exception as e:
            print("e:", e)
            return Response(ElMessage(type="error", msg=str(e)), status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        res.append(diff_result)

        return Response(ElMessage(data='\n'.join(res), type="success"), status=status.HTTP_200_OK)





"""
    单线程，先注释
"""
# '''
#     通过项目id获取某个项目的分支或者某个 tag 的目录树
# '''
# class repositoryTree(viewsets.ViewSet,
#                      viewsets.mixins.ListModelMixin,
#                      viewsets.mixins.RetrieveModelMixin, ):
#
#     def retrieve(self, request, *args, **kwargs):
#         begin_time = time.time()
#         gitlabClient = gitlabApi.gitlabClient()
#
#         project_id = self.kwargs.get('pk')
#         ref = request.GET.get('ref', 'main')
#         print("pk:", project_id, "ref:", ref)
#
#         try:
#             project = gitlabClient.projects.get(project_id)
#             items = project.repository_tree(ref=ref, recursive=True)
#         except gitlab.exceptions.GitlabGetError as e:
#             return JsonResponse({'error': str(e)}, status=400)
#         end_time = time.time()
#         print("itme:", end_time - begin_time)
#
#         return JsonResponse(items, safe=False)



'''
    通过项目id获取某个项目的分支或者某个 tag 的目录树（协程）
'''
class repositoryTree(viewsets.ViewSet,
                     viewsets.mixins.ListModelMixin,
                     viewsets.mixins.RetrieveModelMixin, ):

    def retrieve(self, request, *args, **kwargs):
        import datetime
        # print(f"调用开始时间：", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))


        gitlabClient = gitlabApi.gitlabClient()

        project_id = self.kwargs.get('pk')
        ref = request.GET.get('ref', 'main')
        # print("pk:", project_id, "ref:", ref)


        try:
            project = gitlabClient.projects.get(project_id)
            items = project.repository_tree(ref=ref, recursive=True)
        except gitlab.exceptions.GitlabGetError as e:
            return JsonResponse({'error': str(e)}, status=400)

        return JsonResponse(items, safe=False)


'''
    获取所有的项目和每个项目有哪些分支、哪些 tag
'''
class projectTree(viewsets.ViewSet,
                  viewsets.mixins.ListModelMixin, ):

    def list(self, request, *args, **kwargs):
        gitlabClient = gitlabApi.gitlabClient()

        projectTrees = []

        ## 获取到所有项目对象列表
        projectList = gitlabApi.projectsFromToken(gitlabClient)
        for project in projectList:
            # projectTrees.append({"value": project.id, "label": project.name})
            data = {"value": project.id, "label": project.name,
                    "children": [{"value": "branch", "label": "branch", "children": []},
                                 {"value": "tag", "label": "tag", "children": []}]}
            branchchs = project.branches.list()
            for branchch in branchchs:
                data["children"][0]["children"].append({"value": branchch.name, "label": branchch.name})

            tags = project.tags.list()

            if not tags:
                data["children"].pop(1)

            if tags:
                for tag in tags:
                    data["children"][1]["children"].append({"value": tag.name, "label": tag.name})

            projectTrees.append(data)

        return JsonResponse(projectTrees, safe=False)


'''
    配置 gitlab 配置文件比对页面的默认查询框内容
'''
from .models import FileDiffDefaultField
from .serializers import GetGitlabFileBodySerializer


'''
    配置对比的 select 框默认值
'''
class FileDiffDefaultFieldView(viewsets.ModelViewSet):
    queryset = FileDiffDefaultField.objects.all()
    serializer_class = GetGitlabFileBodySerializer


from utils.views import ElMessage

'''
    创建tag
'''
class tagManager(viewsets.ViewSet,
                 viewsets.mixins.ListModelMixin,
                 viewsets.mixins.RetrieveModelMixin,
                 viewsets.mixins.CreateModelMixin,):
    def create(self, request, *args, **kwargs):
        data = request.data
        ref = request.data.pop('ref', "main")
        # print("ref", ref)
        projectIdList = data["projectID"]
        tagName = data["tagName"]

        try:
            gitlabClient = gitlabApi.gitlabClient()
            projects = gitlabApi.projectsFromId(gitlabClient, projectIdList)
        except Exception as e:
            return Response(ElMessage(f"{e}", type="error"), status=400)

        for project in projects:
            try:
                project.tags.create({'tag_name': f'{tagName}', 'ref': f'{ref}'})
            except Exception as e:
                # return Response(ElMessage(f"{e}", type="error"), status=400)
                # ddSend().send_text(f"{project.name} 项目创建 tag 失败：{e}")
                print(e)

        return Response(ElMessage("创建 tag 任务提交成功", type="success"), status=status.HTTP_200_OK)


'''
    创建tag
'''
@shared_task
def createTag(project: object, ref: str, tagName: str):
    try:
        time.sleep(random.randint(10, 40))
        project.tags.create({'tag_name': f'{tagName}', 'ref': f'{ref}'})
    except Exception as e:
        # return Response(ElMessage(f"{e}", type="error"), status=400)
        # ddSend().send_text(f"{project.name} 项目创建 tag 失败：{e}")
        FsLog(f'{project.name} 项目创建 tag 失败：{e}')
        print(e)
@shared_task
def createTagNew(projectId: int, ref: str, tagName: str):
    gitlabClient = gitlabApi.gitlabClient()
    try:
        project = gitlabClient.projects.get(projectId)
        time.sleep(random.randint(10, 40))
        print("project_name:", project.name)
        project.tags.create({'tag_name': f'{tagName}', 'ref': f'{ref}'})
        return "ok"
    except Exception as e:
        # return Response(ElMessage(f"{e}", type="error"), status=400)
        # ddSend().send_text(f"{project.name} 项目创建 tag 失败：{e}")
        FsLog(f'{project.name} 项目创建 tag 失败：{e}')
        print(e)
        return str(e)

class tagCelery(viewsets.ViewSet,
                 viewsets.mixins.ListModelMixin,
                 viewsets.mixins.RetrieveModelMixin,
                 viewsets.mixins.CreateModelMixin,):
    def create(self, request, *args, **kwargs):
        data = request.data
        ref = request.data.pop('ref', "master")
        # print("ref", ref)
        projectIdList = data["projectID"]
        # print("projectIdList", projectIdList)
        tagName = data["tagName"]
        # gitlabClient = gitlabApi.gitlabClient()
        # try:
        #     projects = gitlabApi.projectsFromId(gitlabClient, projectIdList)
        # except Exception as e:
        #     return Response(ElMessage(f"{e}", type="error"), status=400)

        task_ids = []

        for projectId in projectIdList:
            result = createTagNew.apply_async(args=[projectId, ref, tagName])
            task_ids.append(result.id)

        # for project in projects:
        #     print("project", project)
        #     try:
        #         result = createTag.apply_async(args=[project, tagName, ref])
        #         task_ids.append(result.id)
        #     except Exception as e:
        #         print("xxx", e)
        return Response(ElMessage("创建 tag 任务提交成功", type="success", data=task_ids), status=status.HTTP_200_OK)



"""
    异步接口测试
"""
class asyncExample(viewsets.ViewSet,
                   viewsets.mixins.ListModelMixin,
                   viewsets.mixins.RetrieveModelMixin,
                   viewsets.mixins.CreateModelMixin,
                   viewsets.mixins.UpdateModelMixin, ):

    def list(self, request, *args, **kwargs):
        time.sleep(5)
        return JsonResponse({"msg": "aaa"})



"""
    celery 异步测试
"""
@app.task
def task_name():
    # 任务执行的代码
    # ...
    time.sleep(5)

    # 获取 channel_layer
    channel_layer = get_channel_layer()

    # 发送任务状态到前端
    async_to_sync(channel_layer.group_send)('task_status_group', {
        'type': 'task_status',
        'message': 'Task name is completed.',
    })

    # 发送结果到前端
    async_to_sync(channel_layer.group_send)('task_result_group', {
        'type': 'task_result',
        'message': 'Task result is successful.',
    })

class celeryExample(viewsets.ViewSet,
                   viewsets.mixins.ListModelMixin,
                   viewsets.mixins.RetrieveModelMixin,
                   viewsets.mixins.CreateModelMixin,
                   viewsets.mixins.UpdateModelMixin, ):

    def list(self, request, *args, **kwargs):
        # n = datetime.datetime.now()
        # tz = get_current_timezone()
        # n = tz.localize(n)
        # result = self.mul.apply_async(args=[5,6], )
        result = task_name.apply_async()
        return Response({"msg": result.id})

    @shared_task
    def mul(x, y):
        return x * y

    @shared_task(ignore_result=True)
    def noResult(x, y):
        print(x,y)